<!DOCTYPE html>
<html lang="zh">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>类的使用</title>
  </head>
  <body>
    <script type="module">
      // 引入three.js
      import * as THREE from "three";
      import { scene, camera } from "/src/utils/init.js";

      // 1.定义基类以及属性和方法
      class BaseModel {
        constructor(scene) {
          // this：子类对象
          this.model = null;
          this.scene = scene;
          this.color = new THREE.Color(
            `rgb(
            ${Math.floor(Math.random() * 256)},
            ${Math.floor(Math.random() * 256)},
            ${Math.floor(Math.random() * 256)})`
          );
          this.position = [
            Math.floor(Math.random() * (5 - 0 + 1) + 0),
            Math.floor(Math.random() * (5 - 0 + 1) + 0),
            Math.floor(Math.random() * (5 - 0 + 1) + 0),
          ];
        }

        // 修改颜色
        randColor() {
          this.model.material.color = new THREE.Color(
            `rgb(
            ${Math.floor(Math.random() * 256)},
            ${Math.floor(Math.random() * 256)},
            ${Math.floor(Math.random() * 256)})`
          );
        }
      }

      // 2.定义立方体MyCube类以及属性和方法 并继承基类
      class MyCube extends BaseModel {
        constructor(scene) {
          // 如果子类有 constructor,必须在第一行调用 super() 才能触发父类的构造方法并绑定公共属性和方法，
          // super 会把当前所在函数内 this值传递给父类构造函数内 this 值
          super(scene);
          this.size = [
            Math.floor(Math.random() * (3 - 1 + 1) + 1),
            Math.floor(Math.random() * (3 - 1 + 1) + 1),
            Math.floor(Math.random() * (3 - 1 + 1) + 1),
          ];

          this.init();
        }

        // 初始化
        init() {
          const geometry = new THREE.BoxGeometry(...this.size);
          const material = new THREE.MeshBasicMaterial({ color: this.color });
          const mesh = new THREE.Mesh(geometry, material);
          mesh.position.set(...this.position);
          this.scene.add(mesh);
          this.model = mesh; // 为了以后在别的方法里可以访问到这个mesh物体（颜色修改/旋转操控）
        }

        // 修改颜色
        randColor() {
          this.model.material.color = new THREE.Color(
            `rgb(
            ${Math.floor(Math.random() * 256)},
            ${Math.floor(Math.random() * 256)},
            ${Math.floor(Math.random() * 256)})`
          );
        }

        // 修改角度值
        rotate() {
          this.model.rotation.set(0, Math.PI / 4, 0);
        }
      }

      // 3.定义球体 MySphere 类 并继承基类
      class MySphere extends BaseModel {
        constructor(scene) {
          super(scene);
          this.radius = Math.floor(Math.random() * (2 - 1 + 1) + 1);

          this.init();
        }
        init() {
          const geometry = new THREE.SphereGeometry(this.radius, 32, 16);
          const material = new THREE.MeshBasicMaterial({ color: this.color });
          const mesh = new THREE.Mesh(geometry, material);
          mesh.position.set(...this.position);
          this.scene.add(mesh);
          this.model = mesh; // 为了以后在别的方法里可以访问到这个mesh物体（颜色修改/旋转操控）
        }
      }

      const arr = []; // 装入我们自己的立方体数组
      for (let i = 0; i < 5; i++) {
        arr.push(new MySphere(scene));
        arr.push(new MyCube(scene));
      }
      camera.position.set(-5, 5, -2);

      // 双击修改颜色
      window.addEventListener("dblclick", () => {
        arr.forEach((cube) => {
          cube.randColor();
        });
      });
    </script>
  </body>
</html>
